import { login, logout, getInfo } from '@/api/user'
import { getDepartmentList } from '@/api/department'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'
import rsaEncrypt from '@/utils/rsa'

import Layout from '@/layout'
import { constantRoutes } from '@/router'
import { Message } from 'element-ui'
import { getUserRoutes } from '@/api/menu'

const getDefaultState = () => {
  return {
    token: getToken(),
    name: '',
    avatar: '',
    type: '',
    departmentId: '',
    tmpDepartmentId: '',
    adminId: '',
    // 最终生成的路由
    routes: [],
    // 根据用户信息添加的路由
    addRoutes: [],
    menuList: [],
    departmentList: []
  }
}

const state = getDefaultState()

const mutations = {
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_TYPE: (state, type) => {
    state.type = type
  },
  SET_DEPARTMENT: (state, departmentId) => {
    state.departmentId = departmentId
  },
  SET_DEPARTMENT_TMP: (state, departmentId) => {
    state.tmpDepartmentId = departmentId
  },
  SET_ID: (state, adminId) => {
    state.adminId = adminId
  },
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  },
  SET_DEPARTMENT_LIST: (state, list) => {
    state.departmentList = list
  },
}

const actions = {
  // user login
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    var passwordEncrypt = rsaEncrypt(password)
    return new Promise((resolve, reject) => {
      login({ adminUsername: username.trim(), adminPassword: passwordEncrypt }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data)
        setToken(data)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo().then(response => {
        const { data } = response

        if (!data) {
          reject('验证失败，请重新登录。')
        }

        const { adminId, adminName, adminType, departmentId } = data

        commit('SET_NAME', adminName)
        commit('SET_AVATAR', '@/assets/avatar/avatar.jpg')
        commit('SET_TYPE', adminType)
        commit('SET_DEPARTMENT', departmentId)
        commit('SET_ID', adminId)

        //生成departmentList 并初始化tmpDepartmentId
        fetchDepartmentList()
          .then(departmentList => {
            commit('SET_DEPARTMENT_LIST', departmentList)

            const tmpDepartmentId = initTmpDepartmentId(departmentId, departmentList)
            commit('SET_DEPARTMENT_TMP', tmpDepartmentId)

            resolve(departmentList)
          })
          .catch(error => {
            reject(error)
          })

        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  changeDepartmentTmp({ commit, state }, newValue) {
    commit('SET_DEPARTMENT_TMP', newValue)
  },

  // user logout
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // must remove  token  first
        resetRouter()
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 移除 token
  resetToken({ commit }) {
    return new Promise(resolve => {
      removeToken() // must remove  token  first
      commit('RESET_STATE')
      resolve()
    })
  },

  // 更新 token
  updateToken({ commit }, newToken) {
    return new Promise(resolve => {
      commit('SET_TOKEN', newToken)
      setToken(newToken)
      resolve()
    })
  },

  generateRoutes({ commit }) {
    return new Promise((resolve, reject) => {
      getRoutes(commit)
        .then(accessedRoutes => {
          commit('SET_ROUTES', accessedRoutes)
          resolve(accessedRoutes)
        })
        .catch(error => {
          reject(error)
        })
    })
  }
}

// get departmentList
async function fetchDepartmentList() {
  return new Promise((resolve, reject) => {
    getDepartmentList().then(response => {
      const { data } = response

      if (!data) {
        reject('获取分局列表失败。')
      }

      const tmpList = response.data
      const departmentList = []
      for (let i = 0; i < tmpList.length; i++) {
        departmentList.push(
          {
            key: tmpList[i].departmentId,
            value: tmpList[i].departmentName
          }
        )
      }
      resolve(departmentList)
    }).catch(error => {
      reject(error)
    })
  })
}

function initTmpDepartmentId(departmentId, departmentList) {
  if (departmentId === 0) { // 全部分局情况 自动选择第一个分局
    return departmentList[1].key
  } else {
    return departmentId
  }
}

async function getRoutes(commit) {
  const ret = await getUserRoutes()
  let menuList = ret.data
  if (menuList.length == 0) {
    Message({
      message: '当前用户没有任何权限，请分配权限后再登录！',
      type: 'error',
      duration: 10 * 1000,
      showClose: true
    })
    // eslint-disable-next-line no-throw-literal
    throw '当前用户没有任何权限，请分配权限后再登录！'
  }
  const menuRouters = []
  let menu
  for (let i = 0; i < menuList.length; i++) {
    menu = menuList[i]
    if (!menu.pid) {
      const module = {
        alwaysShow: true,
        path: '/' + menu.url,
        redirect: '/' + menu.url + '/' + menu.redirect,
        component: Layout,
        name: menu.menuCode,
        meta: { id: menu.menuId, title: menu.menuName, icon: menu.icon, fullPath: '/' + menu.url }
      }
      menuRouters.push(module)
      menuList.splice(i--, 1)
    }
  }

  let removeMenuList = []
  for (let i = 0; i < menuRouters.length; i++) {
    convertTree(menuList, menuRouters[i], removeMenuList)
    const removeIds = removeMenuList.map(item => item.menuId)
    menuList = menuList.filter(item => {
      return !removeIds.includes(item.menuId)
    })
    removeMenuList = []
  }
  // 添加最终匹配 404 page
  menuRouters.push({ path: '*', redirect: '/404', hidden: true })
  return menuRouters
}

// 递归中组装树结构
function convertTree(menuList, router, removeMenuList) {
  menuList.forEach((m, i) => {
    if (m.pid && m.pid == router.meta.id) {
      if (!router.children) router.children = []
      const viewpath = m.component
      const menu = {
        path: m.url,
        name: m.menuCode,
        // component: () => import(`@/views${viewpath}`),
        component(resolve) {
          require([`@/views/${viewpath}`], resolve)
        },
        hidden: m.hidden === 1,
        meta: { id: m.menuId, title: m.menuName, icon: m.icon, fullPath: viewpath }
      }
      router.children.push(convertTree(menuList, menu, removeMenuList))
      removeMenuList.push(m)
    }
  })
  return router
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

